#include "PrecompiledHeaders.h"
#include "DefaultPhysics.h"
#include "Ball.h"
#include "TeleportControl.h"
#include "PickupControl.h"
#include "MovingObject.h"
#include "ScoreObjectControl.h"
#include "ScoreToppleControl.h"

/*
int DefaultPhysics::CollisionFilter(OgreNewt::Body *body0, OgreNewt::Body *body1)
{
    return (body0->getType() % BODY_TYPE_COUNT == BT_LEVEL) || 
           (body1->getType() % BODY_TYPE_COUNT == BT_LEVEL) ||
           (body0->getType() / BODY_TYPE_COUNT == body1->getType() / BODY_TYPE_COUNT);
           
}
*/
void DefaultPhysics::gravityCallback( OgreNewt::Body* me )
{
    Ogre::Real mass;
    Ogre::Vector3 inertia;
    me->getMassMatrix(mass, inertia);
    me->setForce(gravity * mass);
}

int DefaultPhysics::userProcess()
{
    BodyType bt_0 (m_body0->getType());
    BodyType bt_1 (m_body1->getType());
            
    // if different players then ignore collisions
    if ( bt_0.getPlayerID() != 0 && 
         bt_1.getPlayerID() != 0 && 
         bt_0.getPlayerID() != bt_1.getPlayerID()) return 0;
    
    // filter invalid moving object collisions
    if (bt_0.getSpecialType() == BodyType::SP_MOVING_OBJECT)
    {
        if (bt_1.getSpecialType() == BodyType::SP_MOVING_OBJECT || bt_1.isActive() == false)
            return 0;
    }
    else if (bt_1.getSpecialType() == BodyType::SP_MOVING_OBJECT)
    {
        if (bt_0.getSpecialType() == BodyType::SP_MOVING_OBJECT || bt_0.isActive() == false)
            return 0;
    }
    
    if (bt_0.getSpecialType() == BodyType::SP_SCORE_GOAL)
    {
        if (bt_1.getSpecialType() == BodyType::SP_SCORE_OBJECT)
        {
            ((ScoreObjectControl*)m_body1->getUserData())->collision(m_body1);
            return 0;
        }
    }
    if (bt_1.getSpecialType() == BodyType::SP_SCORE_GOAL)
    {
        if (bt_0.getSpecialType() == BodyType::SP_SCORE_OBJECT)
        {
            ((ScoreObjectControl*)m_body0->getUserData())->collision(m_body0);
            return 0;
        }
    }
    
    if (bt_0.getSpecialType() == BodyType::SP_SCORE_TOPPLE)
        ((ScoreToppleControl*)m_body0->getUserData())->collision(m_body0);
    
    if (bt_1.getSpecialType() == BodyType::SP_SCORE_TOPPLE)
        ((ScoreToppleControl*)m_body1->getUserData())->collision(m_body1);
    
    if (bt_0.getSpecialType() == BodyType::SP_BALL)
        return processBallCollision(m_body0, m_body1, bt_1);
    else if (bt_1.getSpecialType() == BodyType::SP_BALL)
        return processBallCollision(m_body1, m_body0, bt_0);
    else if (bt_0.getSpecialType() == BodyType::SP_PICKUP)
        return 0;
    else if (bt_1.getSpecialType() == BodyType::SP_PICKUP)
        return 0;
    else    
        return 1;
}

int DefaultPhysics::processBallCollision(OgreNewt::Body *ball_body, OgreNewt::Body *other_body, BodyType &other_type)
{
    Ball *ball = (Ball *) ball_body->getUserData();
    int ret_val = 1;
    Ogre::Vector3 pos, norm;
    if (ball)
    {
        getContactPositionAndNormal(pos, norm);
        //printf("  %f %f %f\n", norm.x, norm.y, norm.z);
        
        Ogre::String obj("");
        
        switch (other_type.getSpecialType())
        {
            case BodyType::SP_TELEPORT:
                obj = "Teleport";
                //fprintf(PlayState::out_file, "Teleport collision\n");
                ball->getPlayer()->getTeleportControl()->ballCollision(other_body, ball_body);
            break;
            
            case BodyType::SP_GOAL:
                obj = "Goal";
                //fprintf(PlayState::out_file, "Goal collision\n");
                ball->goalCollision();
            break;
            
            case BodyType::SP_PICKUP:
                obj = "Pickup";
                //fprintf(PlayState::out_file, "Pickup collision\n");
                ball->getPlayer()->getPickupControl()->pickupHit((unsigned) other_body->getUserData());
                ret_val = 0;
            break;
            
            case BodyType::SP_MOVING_OBJECT:
                obj = "Moving Object";
                //fprintf(PlayState::out_file, "collision %f %f %f %f\n", getContactForce().x, getContactForce().y, getContactForce().z, getContactNormalSpeed());
                //fprintf(PlayState::out_file, "pos %f %f %f\n", pos.x, pos.y, pos.z);
                ((MovingObject *)other_body->getUserData())->ballCollision();
            break;
        }
    
        fprintf(PlayState::out_file, "Ball collision with '%s': %f %f %f %f\n", obj.c_str(), getContactForce().x, getContactForce().y, getContactForce().z, getContactNormalSpeed());
    }
    
    if (ret_val) ball->collision(pos, norm);
    
    return ret_val;
}
